<?php

/**
 * Model che rappresenta un associazione Cliente-Offerta nel DB.
 */
class ArticoloOfferta extends StdModel
{

	private static $singleton = NULL;

	/**
	 * Ritorna una istanza globale di questo model.
	 * @return mixed La istanza globale.
	 */
	public static function getInstance()
	{
		if(self::$singleton == NULL)
			self::$singleton = new ArticoloOfferta();
		return self::$singleton;
	}

	/*
	 * Specifiche attributi del tipo del Model rappresentato da questa classe
	 */
	public $attribTableName = "ArticoloOfferta";
	public $attribLabel = array("idArticolo", "idOfferta");
	public $attribNames = array(STD_ID, "idArticolo", "idOfferta", "TipoModificabile", "DescrizioneBreveModificabile");
	public $attribExcludeFromAdd = array(STD_ID);
	public $attribExcludeFromEdit = array(STD_ID);
	public $attribLongNames = array(STD_ID => "ID", "idArticolo" => "Articolo", "idOfferta" => "Offerta",
		"TipoModificabile" => "Tipo", "DescrizioneBreveModificabile" => "Descrizione breve");
	public $attribIsImportant = array(STD_ID => 0, "idArticolo" => 0, "idOfferta" => 0, "TipoModificabile" => 1,
		"DescrizioneBreveModificabile" => 1);
	//public $attribIsImportant = array(STD_ID => 2, "idAziendaRappresentata" => 1, "Codice" => 1,
		//"PrezzoDiListino" => 1, "PrezzoNetto" => 2, "UM" => 1);
	public $attribIsNumeric = array(STD_ID => true, "idArticolo" => true, "idOfferta" => true, "TipoModificabile" => false,
		"DescrizioneBreveModificabile" => false);
	public $attribIsForeignKey = array(STD_ID => false, "idArticolo" => "Articoli", "idOfferta" => "Offerte",
		"TipoModificabile" => false, "DescrizioneBreveModificabile" => false);

	/**
	 * Restituisce l'HTML per creare un campo di un form adatto a contenere il
	 * valore dell'attribbuto passato. Questo campo di testo sarà vuoto e dovrà
	 * servire per la creazione di una nuova istanza in DB di questo model.
	 * @param string $attribName Nome dell'attributo su cui creare il campo.
	 * @return string Stringa contenente l'HTML dell'elemento creato.
	 */
	public function getAddFormCodeFromAttribute($db,$attribName)
	{
		if($attribName == STD_ID)
			return "";
		if($attribName == "idArticolo")
			return ModelUtils::getExternalSelectorFormElement($attribName, "externalSelector.php", "Articolo", "", "", true, array("DescrizioneBreveModificabile" => "DescrizioneBreve", "TipoModificabile" => "Tipo") );
		if($attribName == "idOfferta")
			return ModelUtils::getExternalSelectorFormElement($attribName, "externalSelector.php", "Offerta", "", "", true, NULL );
		if($attribName == "DescrizioneBreveModificabile")
		{
			$defaultVal = $this->chachedArticolo == NULL ? "" : $this->chachedArticolo->dataTupla["DescrizioneBreve"];
			return "<br/>".ModelUtils::getLongTextFormElement($attribName, $defaultVal, 50, 7);
		}
		if($attribName == "TipoModificabile")
			return ModelUtils::getTextFormElement($attribName, "", false, 0);
		return "";
	}

	/**
	 * Restituisce l'HTML per creare un campo di testo adatto a contenere il
	 * valore dell'attribbuto passato. Questo campo di testo conterrà il valore
	 * attualmente assunto da questo attributo in questa tupla.
	 * @param DatabaseManager $db Database su cui effettuare una possibile
	 * interrogazione.
	 * @param string $attribName Nome dell'attributo di cui creare il codice.
	 * @return string Il codice HTML dell'elemento form corrispondente.
	 */
	public function getEditFormCodeFromAttribute($db, $attribName)
	{
		if($attribName == STD_ID)
			return ModelUtils::getHiddenFormElement($attribName, $this->dataTupla[$attribName], true);
		if($attribName == "DescrizioneBreveModificabile")
			return ModelUtils::getLongTextFormElement($attribName, $this->dataTupla[$attribName], NULL, NULL);
		if($attribName == "TipoModificabile")
			return ModelUtils::getTextFormElement($attribName, $this->dataTupla[$attribName], false, NULL);
		return "";
	}

	/**
	 * Costruttore che acquisisce l'array dei valori associativi.
	 * @param type $data L'array associativo a cui inizializzare questa istanza.
	 */
	public function __construct($data = NULL)
	{
		parent::__construct($data);
	}

	/**
	 * Crea una nuova istanza della sottoclasse specializzante.
	 * @param array $data I dati passati da cui recuperare i valori.
	 * @return mixed Una nuova instanza della sottoclasse specializzante.
	 */
	public function createNew($data)
	{
		return new ArticoloOfferta($data);
	}

	/**
	 * Duplica tutte le tuple di questo model con l'id offerta specificato
	 * ed imposta nelle nuove tuple come id offerta il valore idOfferta passato.
	 * @param DatabaseManager $db Database da interrogare.
	 * @param int $idVecchiaOfferta ID vecchia offerta delle tuple da duplicare.
	 * @param int $idNuovaOfferta ID nuova offerta da impostare nelle nuove tuple.
	 */
	public function duplicateFromIDOfferta($db,$idVecchiaOfferta,$idNuovaOfferta)
	{
		return $db->AddRecordsWithSELECT($this->attribTableName, "idArticolo, idOfferta, TipoModificabile, DescrizioneBreveModificabile",
				"SELECT idArticolo, ".$idNuovaOfferta.", TipoModificabile, DescrizioneBreveModificabile FROM ".$this->attribTableName." WHERE idOfferta = ".$idVecchiaOfferta);
	}

	/**
	 * Rimuove dal DB la tupla rappresentata da questa instanza.
	 * @param DatabaseManager $db Database su cui effettuare il REMOVE.
	 * @return boolean Restituisce vero se il REMOVE è andato a buon fine, falso
	 * altrimenti.
	 */
	public function removeFromDB($db)
	{
		//ha bisogno del campo idArticolo che carichiamo se non è già stato
		//precaricato:
		if(!isset($this->dataTupla["idArticolo"]) || $this->dataTupla["idArticolo"] === NULL)
			$this->dataTupla["idArticolo"] = $db->GetValueFromRecords($this->attribTableName, "idArticolo", STD_ID." = ".$this->dataTupla[STD_ID]);
		if($this->dataTupla["idArticolo"] === NULL)
			return false;
		//Rimuove tutte le variazoni articoli offerti appartenenti a questo articolo offerto, e poi rimuove questo articolo offerto.
		//La query raccoglie tutte le variazioni articoli offerte in JOIN con le variazioni articoli in modo da acquisire
		//tutti gli ID delle tuple che fanno parte della sotto associazione tra le singole variazioni articoli offerte,
		//con l'articolo offerto, e con la offerta stessa, ed elimina tutte le tuple che hanno uno di questi ID
		//(ovvero vengono eliminate tutte le suddette tuple).
		$rs = $db->EnumerateTableStartExt("VariazioneArticoloOfferta.ID AS IDToRemove ",//select
				"VariazioneArticoloOfferta LEFT JOIN VariazioneArticolo ".//from
				"ON VariazioneArticoloOfferta.idVariazioneArticolo = VariazioneArticolo.ID ",
				"",//order by
				"idOfferta = ".$this->dataTupla["idOfferta"]." AND idArticolo = ".$this->dataTupla["idArticolo"]//where
				);
		if($rs == FALSE)
			return false;
		$IDsToRemoveStr = "";
		if($db->EnumerateTableNext($rs))//primo senza virgola separatrice
			$IDsToRemoveStr = $db->EnumerateTableGetValue ($rs, "IDToRemove");
		while($db->EnumerateTableNext($rs))//altri con virgola separatrice
			$IDsToRemoveStr .= ", ".$db->EnumerateTableGetValue ($rs, "IDToRemove");
		/*$cond = "ID IN ( ".
				"SELECT VariazioneArticoloOfferta.ID AS IDToRemove ".
				"FROM VariazioneArticoloOfferta LEFT JOIN VariazioneArticolo ".
				"ON VariazioneArticoloOfferta.idVariazioneArticolo = VariazioneArticolo.ID ".
				"WHERE idOfferta = ".$this->dataTupla["idOfferta"]." AND idArticolo = ".$this->dataTupla["idArticolo"].
				" )";*/
		if($IDsToRemoveStr == "")//se non ci sono sotto variazioni da eliminare
			return parent::removeFromDB($db);
		else
		{
			$cond = "ID IN ( ".$IDsToRemoveStr." ) ";
			$res = $db->EraseRecords("VariazioneArticoloOfferta", $cond);
			if($res !== FALSE)
				return parent::removeFromDB($db);
		}
	}

	const getOfferteJoinTable  = "ArticoloOfferta LEFT JOIN Offerta ON ArticoloOfferta.idOfferta = Offerta.ID";
	const getOfferteJoinSelect = "Offerta.*, ArticoloOfferta.ID AS IDAssoc, idArticolo, idOfferta, TipoModificabile, DescrizioneBreveModificabile";

	public $chachedOfferta = NULL;

	const getArticoloJoinTable  = "ArticoloOfferta LEFT JOIN Articolo ON ArticoloOfferta.idArticolo = Articolo.ID";
	const getArticoloJoinSelect = "Articolo.*, ArticoloOfferta.ID AS IDAssoc, idArticolo, idOfferta, TipoModificabile, DescrizioneBreveModificabile";

	public $chachedArticolo = NULL;

	/**
	 * Crea una nuova istanza della sottoclasse specializzante.
	 * @param array $data I dati passati da cui recuperare i valori.
	 * @return mixed Una nuova instanza della sottoclasse specializzante.
	 */
	public function createNewWithArticolo($data)
	{
		$cc = Articolo::getInstance()->createNew($data);
		$data[STD_ID] = $data["IDAssoc"];
		$newinstance = $this->createNew($data);
		$newinstance->chachedArticolo = $cc;
		return $newinstance;
	}

	/**
	 * Crea una nuova istanza della sottoclasse specializzante.
	 * @param array $data I dati passati da cui recuperare i valori.
	 * @return mixed Una nuova instanza della sottoclasse specializzante.
	 */
	public function createNewWithOfferta($data)
	{
		$co = Offerta::getInstance()->createNew($data);
		$data[STD_ID] = $data["IDAssoc"];
		$newinstance = $this->createNew($data);
		$newinstance->chachedOfferta = $co;
		return $newinstance;
	}

	/**
	 * Restituisce una lista di associazioni di offerte di un dato articolo.
	 * @param DatabaseManager $db Database da interrogare.
	 * @param int $idArticolo Id articolo di cui restituire le offerte associate.
	 * @return array L'array di elementi trovati o NULL in caso di errore.
	 */
	public function getListFromDBByIDArticolo($db, $idArticolo)
	{
		$rs = $db->EnumerateTableStartExt(self::getOfferteJoinSelect,self::getOfferteJoinTable,"","idArticolo = ".$idArticolo,"");
		if($rs == FALSE)
			return NULL;
		$retarr = array();
		while($db->EnumerateTableNext($rs))
			$retarr[] = $this->createNewWithOfferta($db->EnumerateTableGetValues($rs));
		return $retarr;
	}

	/**
	 * Restituisce una lista di associazioni di articoli di una data offerta.
	 * @param DatabaseManager $db Database da interrogare.
	 * @param int $idOfferta Id offerta di cui restituire i clienti associati.
	 * @return array L'array di elementi trovati o NULL in caso di errore.
	 */
	public function getListFromDBByIDOfferta($db, $idOfferta)
	{
		$rs = $db->EnumerateTableStartExt(self::getArticoloJoinSelect,self::getArticoloJoinTable,"","idOfferta = ".$idOfferta,"");
		if($rs == FALSE)
			return NULL;
		$retarr = array();
		while($db->EnumerateTableNext($rs))
			$retarr[] = $this->createNewWithArticolo($db->EnumerateTableGetValues($rs));
		return $retarr;
	}

	/**
	 * Ritorna una istanza di Articolo corrispondente alla chiave esterna
	 * "idArticolo" di questa tupla.
	 * @param DatabaseManager $db Database da interrogare.
	 * @return Articolo L'instanza creata o NULL in caso di errore.
	 */
	public function getArticolo($db)
	{
		$idag = isset($this->dataTupla["idArticolo"]) ? $this->dataTupla["idArticolo"] : NULL;
		if($idag != NULL && $idag > 0)
		{
			if($this->chachedArticolo == NULL || $this->chachedArticolo->dataTupla[STD_ID] != $idag)
			{
				$this->chachedArticolo = Articolo::getInstance()->getFromDB($db, $this->dataTupla["idArticolo"]);
				return $this->chachedArticolo;
			}
			else
				return $this->chachedArticolo;
		}
		return NULL;
	}

	/**
	 * Ritorna una istanza di Offerta corrispondente alla chiave esterna
	 * "idOfferta" di questa tupla.
	 * @param DatabaseManager $db Database da interrogare.
	 * @return Offerta L'instanza creata o NULL in caso di errore.
	 */
	public function getOfferta($db)
	{
		$idag = isset($this->dataTupla["idOfferta"]) ? $this->dataTupla["idOfferta"] : NULL;
		if($idag != NULL && $idag > 0)
		{
			if($this->chachedOfferta == NULL || $this->chachedOfferta->dataTupla[STD_ID] != $idag)
			{
				$this->chachedOfferta = Offerta::getInstance()->getFromDB($db, $this->dataTupla["idOfferta"]);
				return $this->chachedOfferta;
			}
			else
				return $this->chachedOfferta;
		}
		return NULL;
	}

	private static $assocAttribLongNames = array(STD_ID => "ID", "idAziendaRappresentata" => "Produttore", "TipoModificabile" => "Tipo",
		"DescrizioneBreveModificabile" => "Descrizione breve", "UM" => "Unit&agrave; di misura", "Nome" => "Nome");

	/**
	 * Restituisce gli attributi che danno maggiori informazioni di questa tupla
	 * come ad esempio gli attributi di un oggetto specificato da una chiave
	 * esterna.
	 * @return array L'array esteso di nomi di attributi.
	 */
	public function getExtendedInfoAttributeLongNames()
	{
		return self::$assocAttribLongNames;
	}

	/**
	 * Metodo che restituisce una etichetta che rappresenta il valore di un
	 * attributo: nella sua versione di default ritorna esattamente il valore
	 * associato a quell'attributo, ma è possibile implementarlo nelle
	 * sottoclassi per specificare opportuni comportamenti, come ad esempio di
	 * non far stampare un numero che rappresenta una chiave esterna, ma invece
	 * una etichetta della tupla ad essa associata.
	 * @param DatabaseManager $db Database su cui poter effettuare una possibile
	 * interrogazione.
	 * @param string $attrib Attributo di cui stampare l'etichetta del valore.
	 * @return string Il valore associato all'attributo o NULL se l'attributo
	 * non è stato trovato.
	 */
	public function getDataLabel($db, $attrib)
	{
		if($attrib == "DescrizioneBreveModificabile" || $attrib == "TipoModificabile")
			return $this->dataTupla[$attrib];
		elseif($attrib == STD_ID && $this->showRealValues_Enabled)
			return $this->dataTupla[STD_ID];
		else
		{
			$art = $this->getArticolo($db);
			$art->cutLongStrings($this->cutDataLabels);
			return $art->getDataLabel($db, $attrib);
		}
	}

	/**
	 * Imposta una flag che determina se tagliare le stringhe lunghe o meno
	 * quando restituite con il metodo getDataLabel().
	 * @param boolean $enabled Se abilitare o meno la flag.
	 */
	public function cutLongStrings($enabled)
	{
		$this->cutDataLabels = $enabled;
		if($this->chachedArticolo != NULL)
			$this->chachedArticolo->cutLongStrings($enabled);
	}

}

?>
